package org.opencare.tmd;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

import javax.jms.JMSException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.opencare.lib.model.edxl.EDXLDistribution;
import org.opencare.tmd.plugin.Publisher;
import org.opencare.tmd.plugin.TopicPublisher;

/**
 * Servlet implementation class TmdPlugin
 */

public class TmdPluginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	static Logger log = Logger.getLogger(TmdPluginServlet.class);
	
	private EDXLBuilder edxlBuilder;
	private Publisher pub;
    private String sender;
    private String topic_uri;
    private String topic_name;
	
    /**
     * @see HttpServlet#HttpServlet()
     */
    public TmdPluginServlet() {
        super();
        // TODO Auto-generated constructor stub              
    }
     
	@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		
		ServletContext sc = config.getServletContext();
		
		System.out.println("TmdPluginServlet is initializing JMS");
		String jmsLocation = config.getInitParameter("jms-properties-location");
		
		if (jmsLocation == null) {
			System.err.println("*** No jms-properties-location init param!!!");
			
		} else {
			String webAppPath = sc.getRealPath("/");
			String jmsProp = webAppPath + jmsLocation;
			File propFile = new File(jmsProp);
			if (propFile.exists()) {
				System.out.println("Initializing log4j with: " + jmsProp);
				Properties prop = new Properties();
				try {
					prop.load(new FileInputStream(jmsProp));
					
					this.sender = prop.getProperty("sender.uri");
					this.topic_uri = prop.getProperty("activemq.topic.url.public");
					this.topic_name = prop.getProperty("activemq.topic.name.public");
					
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					log.fatal(e.toString());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					log.fatal(e.toString());
				}
			} else {
				log.error("*** " + jmsProp + " file not found, so initializing jms, use default value.");
				
				this.sender = "tmd.go.th";
				this.topic_uri = "tcp://localhost:61616";
				this.topic_name = "opencare.messages";								
			}
		}
		
		super.init(config);
		
		edxlBuilder = new EDXLBuilderImpl();
		edxlBuilder.setSender(this.sender);
		
		log.debug("properties list");
		log.debug("sender: " + this.sender);
		log.debug("topic uri: " + this.topic_uri);
		log.debug("topic name: " + this.topic_name);
		
		try {
			pub = new TopicPublisher(this.topic_uri, this.topic_name);
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			log.fatal(e.toString());
		}
		
				
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		super.destroy();
	}


	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setContentType("text/xml; charset=UTF-8");

		PrintWriter out = response.getWriter();

		// Get parameters value		
		String eventID = request.getParameter("eventID");
		String guid = request.getParameter("guid");
		String pubDateString = request.getParameter("pubDate");
		String topic = request.getParameter("title");
		String description = request.getParameter("description");		
		String uri = request.getParameter("link");
		String eventType = request.getParameter("eventType");
		String eventLevel = request.getParameter("eventLevel");
		String disasterType = request.getParameter("disasterType");
		String category = request.getParameter("category");

		/* Print HTTP params */
		log.debug(eventID);
		log.debug(guid);
		log.debug(pubDateString);
		log.debug(topic);
		log.debug(description);		
		log.debug(uri);
		log.debug(eventType);
		log.debug(eventLevel);
		log.debug(disasterType);
		log.debug(category);
				
		// Parameters validation
		if(eventID == null){
			if(guid != null) {
				eventID = guid;			
				eventID += '-';
			}
			
			java.util.Date date= new java.util.Date();
			eventID += Long.toString(new Timestamp(date.getTime()).getTime());			 
		}
		
		Date pubDate;
		if((pubDate = checkDateString(pubDateString)) == null) {
			out.println(getResponseString(-1, "Wrong date format"));
			return;
		}
		
		if((topic == null) || (topic.length() == 0)){
			out.println(getResponseString(-1, "String length for title must greather than 0"));
			return;
		}
		
		if((description == null) || (description.length() == 0)){
			out.println(getResponseString(-1, "String length for description must greather than 0"));
			return;
		}		
		// Build EDXL message
		
		/** 
		 * -- eventType --
		 * ACTUAL
		 * EXERCISE
		 * SYSTEM
		 * TEST
		 **/
		if((eventType == null) || eventType.length() == 0)
			eventType = "ACTUAL";
		if(     eventType.equalsIgnoreCase("ACTUAL") || 
				eventType.equalsIgnoreCase("EXERCISE") || 
				eventType.equalsIgnoreCase("SYSTEM") || 
				eventType.equalsIgnoreCase("TEST")) {
			eventType = eventType.toUpperCase();
		} else {
			out.println(getResponseString(-1, "Supplied eventType not in list"));
			return;
		}	
				
		/**
		 * -- eventLevel --
		 * WARNING     	or RED
		 * WATCH       	or ORANGE
		 * ADVISORY    	or GREEN
		 * TERMINATION
		 */
		if((eventLevel == null) || eventLevel.length() == 0)
			eventLevel = "ADVISORY";
		if(     eventLevel.equalsIgnoreCase("WARNING") || 
				eventLevel.equalsIgnoreCase("WATCH") || 
				eventLevel.equalsIgnoreCase("ADVISORY") || 
				eventLevel.equalsIgnoreCase("TERMINATION") ||
				eventLevel.equalsIgnoreCase("RED") ||
				eventLevel.equalsIgnoreCase("ORANGE") ||
				eventLevel.equalsIgnoreCase("GREEN")) {
			eventLevel = eventLevel.toUpperCase();
		} else {
			out.println(getResponseString(-1, "Supplied eventLevel not in list"));
			return;
		}	
		
		/**
		 * -- disasterType -- 
		 * EARTHQUAKE    
		 * FLOODING      
		 * WILDFIRE      
		 * STORM         
		 * DAM FAILURE   
		 * LAND SLIDE    
		 * CONTAMINATION 
		 * TSUNAMI
		 * OTHER
		 */
		if((disasterType == null) || disasterType.length() == 0)
			disasterType = "OTHER";
		if(     disasterType.equalsIgnoreCase("EARTHQUAKE") || 
				disasterType.equalsIgnoreCase("FLOODING") || 
				disasterType.equalsIgnoreCase("WILDFIRE") || 
				disasterType.equalsIgnoreCase("STORM") ||
				disasterType.equalsIgnoreCase("DAM FAILURE") ||
				disasterType.equalsIgnoreCase("LAND SLIDE") ||
				disasterType.equalsIgnoreCase("CONTAMINATION") ||
				disasterType.equalsIgnoreCase("TSUNAMI") ||
				disasterType.equalsIgnoreCase("OTHER")) {
			disasterType = disasterType.toUpperCase();
		} else {
			out.println(getResponseString(-1, "Supplied disasterType not in list"));
			return;
		}	
		
		/**
		 * -- Categories --
		 * GEO
		 * MET
		 * SAFETY
		 * SECURITY
		 * RESCUE
		 * FIRE
		 * HEALTH
		 * ENV
		 * TRANSPORT
		 * INFRA
		 * CBRNE
		 * OTHER 
		 */
		if((category == null) || category.length() == 0)
			category = "MET";
		if(     category.equalsIgnoreCase("GEO") || 
				category.equalsIgnoreCase("MET") || 
				category.equalsIgnoreCase("SAFETY") || 
				category.equalsIgnoreCase("SECURITY") ||
				category.equalsIgnoreCase("RESCUE") ||
				category.equalsIgnoreCase("FIRE") ||
				category.equalsIgnoreCase("HEALTH") ||
				category.equalsIgnoreCase("ENV") ||
				category.equalsIgnoreCase("TRANSPORT") ||
				category.equalsIgnoreCase("INFRA") ||
				category.equalsIgnoreCase("CBRNE") ||
				category.equalsIgnoreCase("OTHER")) {
			category = category.toUpperCase();
		} else {
			out.println(getResponseString(-1, "Supplied category not in list"));
			return;
		}
			
		// Put convert to EDXL
		EDXLDistribution edxlMessage = edxlBuilder.build(eventID, pubDate, topic,
				description, eventType, eventLevel, disasterType, category, uri);
				
		log.debug(edxlMessage);	
		
		try {
			pub.publish(edxlMessage);
			out.println(getResponseString(0, "success"));
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			log.error(e.toString());
			out.println(getResponseString(-1, "Internal error, can not sent to message broker."));
		}
	}
	
	private String getResponseString(int respCode, String reason){
		StringBuffer str = new StringBuffer();
		
		str.append(("<?xml version=\"1.0\"?>"));  
		str.append("<response id=\""+ respCode +"\">" + reason);
		str.append("</response>");
		
		return str.toString();
	}
	
	private Date checkDateString(String dateString)
	{
		StringBuffer dateBuff = new StringBuffer();
		dateBuff.append(dateString);
		dateBuff.deleteCharAt(dateString.length()-3);
		Date date;
		
		try {
			SimpleDateFormat format = new SimpleDateFormat(
	                "yyyy-MM-dd'T'HH:mm:ssZ", new Locale("en", "US"));
			date = format.parse(dateBuff.toString());
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			log.error(e.toString());
			return null;
		}
		
		return date;		
	}
}
